#ifndef WORKER_H_INCLUDED
#define WORKER_H_INCLUDED

#include <Ape/MT/MailBox.h>
#include <Ape/MT/Task.h>
#include <Ape/EInvalidOperation.h>

namespace Ape {
	namespace MT {
		template <typename Letter_t>
		class Worker : public Task {
			TYPE_NAME ("Ape::MT::Worker")
			bool m_Stopped;
		protected:
			MailBox<Letter_t> m_MailBox;
		public:
			Worker();
			virtual ~Worker();
			
			void Message(const Letter_t& letter);
			
			virtual void Run (EventArgs& ea);
			
			void Stop();
			
			virtual void ProcessMessage(const Letter_t& letter) = 0;
			virtual void HandleError(Ape::Exception& exc);
		};
		
		template <typename Letter_t>
		Worker<Letter_t>::Worker() : m_Stopped(false) {
			Start();
		}
		
		template <typename Letter_t>
		Worker<Letter_t>::~Worker() {
		}
		
		template <typename Letter_t>
		void Worker<Letter_t>::Message(const Letter_t& letter) {
			if (!m_Stopped)
				m_MailBox.Send(letter);
			else
				throw Ape::EInvalidOperation(L"Worker is stopped");
		}
		
		template <typename Letter_t>
		void Worker<Letter_t>::Stop () {
			m_Stopped = true;
			Letter_t letter;
			m_MailBox.Send(letter); // Dummy letter - it will never be read
		}
		
		template <typename Letter_t>
		void Worker<Letter_t>::Run (EventArgs& ea) {
			while (!m_Stopped) {
				Letter_t letter = m_MailBox.Receive();
				if (m_Stopped || letter.LetterType == 0x00) {
					//if (letter.LetterType == 0x00)
					//	printf("death letter");
					return;
				}
				try {
					ProcessMessage(letter);
				}
				catch (Ape::Exception& exc) {
					HandleError(exc);
				}
			}
		}
		
		template <typename Letter_t>
		void Worker<Letter_t>::HandleError(Ape::Exception& exc) {
			exc._Dump(true);
		}
	}
}

#endif // WORKER_H_INCLUDED
